package at.fhj.mobsecdev.cookit.activities;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.Toast;
import at.fhj.mobsecdev.cookit.R;
import at.fhj.mobsecdev.cookit.model.Ingredient;
import at.fhj.mobsecdev.cookit.model.Recipe;
import at.fhj.mobsecdev.cookit.util.Constants;
import at.fhj.mobsecdev.cookit.util.IngredientControlTuple;
import at.fhj.mobsecdev.cookit.util.IngredientControlTupleFactory;
import at.fhj.mobsecdev.cookit.util.RecipeValidator;
import at.fhj.mobsecdev.cookit.webrequests.UploadRecipeAsyncWebCall;
import at.fhj.mobsecdev.cookit.webrequests.UploadRecipeAsyncWebCall.Upload;

/**
 * Activity that displays a form to upload a new recipe
 */
public class ViewAddRecipeActivity extends Activity implements Upload {
	
	private EditText recipeName; 
	private EditText preparation;
	private CheckBox isVegetarian;
	private Spinner difficulty;
	
	private ImageView recipeImage; 
	private LinearLayout ingredientContainer;
	
	/* List that contains Ingredient tuples (Food - Amount) */
	private List<IngredientControlTuple> ingredientControlTupleList = new ArrayList<IngredientControlTuple>();
	
	private SharedPreferences sharedPreferences;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		sharedPreferences = getSharedPreferences(Constants.SHARED_PREFERNECES_CREDENTIALS, Context.MODE_PRIVATE);
		
		/* Restore image file after taking photo */
		if (savedInstanceState != null){
		    recipeImageFilepath = savedInstanceState.getString("imagePath");
		    recipeImageFile = new File(recipeImageFilepath);
		  }
		
		if(sharedPreferences.getString(Constants.PREFERENCE_USERNAME, "username") != "username" &&
				sharedPreferences.getString(Constants.PREFERENCE_PASSWORDHASH, "passwordhash") != "passwordHash") {
			setContentView(R.layout.activity_add_recipe);
			
			ingredientContainer = (LinearLayout) findViewById(R.id.ingredientContainer);
			recipeImage = (ImageView) findViewById(R.id.recipeImage);
			recipeName = (EditText) findViewById(R.id.recipeName);
			preparation = (EditText) findViewById(R.id.preparation);
			difficulty = (Spinner) findViewById(R.id.difficulty);
			isVegetarian = (CheckBox) findViewById(R.id.isVegetarian);
			
			IngredientControlTuple firstIngredientControlTuple = newRecipeControlTuple();
			ingredientContainer.addView(firstIngredientControlTuple.getLayout());
		} else { //if user is not logged in, return back to Main activity
			Intent intent = new Intent(this, LoginActivity.class);
			startActivity(intent);
			finish();
		}
	}
	
	@Override
	protected void onSaveInstanceState(Bundle icicle) {
		/* Save photo path before entering 'taking photo' intent */
		super.onSaveInstanceState(icicle);
		icicle.putString("imagePath", recipeImageFilepath);
	}
	
	/**
	 * Add a new Ingredient tuple (Food - Amount) to the view
	 */
	private IngredientControlTuple newRecipeControlTuple() {
		IngredientControlTuple recipeControlTuple = IngredientControlTupleFactory.get(this);


		recipeControlTuple.getAmount().addTextChangedListener(textwatcher);
		recipeControlTuple.getIngredient().addTextChangedListener(textwatcher);
		
		ingredientControlTupleList.add(recipeControlTuple);
		
		return recipeControlTuple;
	}
	
	/**
	 * Adds a new Ingredient tuple if user inserts text in the last one
	 */
	private TextWatcher textwatcher = new TextWatcher() {
		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			if (s.length() > 0) {
				IngredientControlTuple newAmountIngredientTuple = newRecipeControlTuple();				
				LinearLayout oldAmountIngredientTuple = (LinearLayout) ingredientContainer.getChildAt(ingredientContainer.getChildCount() - 1);
				
				EditText oldAmount = (EditText)oldAmountIngredientTuple.getChildAt(oldAmountIngredientTuple.getChildCount() - 1);
				EditText oldIngredient = (EditText)oldAmountIngredientTuple.getChildAt(oldAmountIngredientTuple.getChildCount() - 2);
				
				ingredientContainer.addView(newAmountIngredientTuple.getLayout());
				
				oldAmount.removeTextChangedListener(textwatcher);
				oldIngredient.removeTextChangedListener(textwatcher);
			}
		}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) { }
		
		@Override
		public void afterTextChanged(Editable s) { }
	};
	
	/**
	 * Calls upload web service with selected data
	 * @param v
	 */
	public void upload(View v)
	{
		Recipe recipeToUpload = new Recipe();
		recipeToUpload.setIngredients(new ArrayList<Ingredient>());
		
		for(IngredientControlTuple controlTuple : ingredientControlTupleList)
		{
			Ingredient ingredient = controlTuple.generateIngredient();
			if(ingredient != null)
			{
				recipeToUpload.getIngredients().add(ingredient);
			}
		}
		recipeToUpload.setIsVegetarian(isVegetarian.isChecked());
		recipeToUpload.setDifficulty(difficulty.getSelectedItem().toString());
		recipeToUpload.setName(recipeName.getText().toString());
		recipeToUpload.setCookingInstruction(preparation.getText().toString());
		
		if(recipeImageFile != null)
		{
		recipeToUpload.setImageFilePath(recipeImageFile.getAbsolutePath());
		}
		
		/* Validate recipe */
		RecipeValidator recipeValidator = new RecipeValidator();
		StringBuilder errorString = new StringBuilder();
		
		if(recipeValidator.validate(recipeToUpload, errorString, this.getResources())) //if everything is correct, call web service
		{
			new UploadRecipeAsyncWebCall(this, sharedPreferences, ViewAddRecipeActivity.this).execute(recipeToUpload);
		}
		else //otherwise display error message
		{
			Toast.makeText(this, errorString.toString(), Toast.LENGTH_LONG).show();
		}
	}
	
	/* Image Handling */
	
	private File recipeImageFile;
	private String recipeImageFilepath;
	private static final int REQUEST_IMAGE_CAPTURE = 1;
	
	/**
	 * Opens 'take photo'-popup
	 * @param v
	 */
	public void takePhoto(View v)
	{
		Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
	    // Ensure that there's a camera activity to handle the intent
	    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
	        // Create the File where the photo should go
	        try {
	        	recipeImageFile = createImageFile();
	        	recipeImageFilepath = recipeImageFile.getAbsolutePath();
	        } catch (IOException ex) {
	        	Toast.makeText(this, getResources().getString(R.string.error_could_not_take_image)  + ": " + ex.getMessage(), Toast.LENGTH_LONG).show();
	        }
	        // Continue only if the File was successfully created
	        if (recipeImageFile != null) {
	            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
	                    Uri.fromFile(recipeImageFile));
	            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
	        }
	    }
	}
	
	/**
	 * Saves resulting photo path in recipe to upload and displays it in ImageView
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		Recipe recipe = new Recipe();
		
	    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
	    	if(recipeImageFile != null) { 
		        Bitmap imageBitmap = BitmapFactory.decodeFile(recipeImageFile.getAbsolutePath());
		        recipeImage.setImageBitmap(imageBitmap);
				recipe.setImageFilePath(recipeImageFile.getAbsolutePath());
	    	}
	    	else {
	    		Toast.makeText(getApplicationContext(), getApplicationContext().getResources().getString(R.string.error_taking_photo_failed), Toast.LENGTH_LONG).show();
	    	}
	    }
	}
	
	/**
	 * Creates a file to save the taken photo
	 * @return the filepath
	 * @throws IOException if there was an error creating the file
	 */
	@SuppressLint("SimpleDateFormat") //time zones don't matter, we just want to have an unique file path
	private File createImageFile() throws IOException {
	    // Create an image file name
	    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
	    String imageFileName = "JPEG_" + timeStamp + "_";
	    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
	    File image = File.createTempFile(
	        imageFileName,  /* prefix */
	        ".jpg",         /* suffix */
	        storageDir      /* directory */
	    );

	    return image;
	}

	/* Callback methods of Upload web service */
	
	@Override
	public void uploadSuccessful() {
		Toast.makeText(this, R.string.upload_successful, Toast.LENGTH_LONG).show();
		
		Intent intent = new Intent(this, MainActivity.class);
		startActivity(intent);
		
	}

	@Override
	public void uploadFailed(String error) {
		Toast.makeText(this, getString(R.string.upload_failed) + ": " + error, Toast.LENGTH_LONG).show();		
	}
}
